/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "V3ApiOperator.h"
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <curl_http/HttpClientInterface.h>
#include "log/Log.h"
#include "common/Macros.h"
#include "system/System.hpp"
#include "common/Constants.h"
#include "common/Structs.h"
#include "config_reader/ConfigIniReader.h"
#include "volume_handlers/common/DiskCommDef.h"
#include "DiskScannerHandler.h"

namespace {
const std::string MODULE_NAME = "V3ApiOperator";
}

namespace VirtPlugin {
/**
 *  @brief 在添加的阵列受保护环境上添加该主机节点需要的一些初始化信息，
 *         如: 1-主机、2-主机组、3-LUN组、4-映射视图
           执行顺序: 创建主机、主机组，添加主机到主机组
                    创建启动器并添加到主机
                    创建LUN组
                    创建映射视图，并将主机组与LUN组添加到其中
           注：扫描LUN时再将LUN添加至LUN组
 *
 *  @return 成功返回 SUCCESS，出错返回 Module::FAILED
 */
int32_t V3ApiOperator::CreateMappingSet(const std::string& objId, MO_TYPE objType)
{
    INFOLOG("Start to create v3 mapping set.");
    if (InitMappingNameInfo() != Module::SUCCESS) {
        return Module::FAILED;
    }
    HostMO hostMO;
    int32_t iRet = CreateInitiatorAndHost(m_hostName, hostMO);
    if (iRet != Module::SUCCESS) {
        return Module::FAILED;
    }
    if (CreateHostGroupAndAddHost(m_hostGroupName, hostMO.m_id) != Module::SUCCESS) {
        return Module::FAILED;
    }
    if (CreateLunGroupAndAddObj(m_lunGroupName, objId, objType) != Module::SUCCESS) {
        return Module::FAILED;
    }
    MappingViewMO mappingViewMO;
    std::string errorDes;
    {
        std::lock_guard<std::mutex> guard(m_mutexMappingView);
        iRet = GetMappingViewByName(m_mappingViewName, mappingViewMO, errorDes);
        if (iRet != Module::SUCCESS || mappingViewMO.m_id.empty()) {
            if (CreateMappingView(m_mappingViewName, mappingViewMO, errorDes) != Module::SUCCESS) {
                ERRLOG("Create mapping view failed, error des:%s", errorDes.c_str());
                return Module::FAILED;
            }
        }
        HostGroupMO hostGroupMO;
        GetHostGroupFromMappingView(mappingViewMO.m_id, hostGroupMO, errorDes);
        if (hostGroupMO.m_id.empty()) {
            if (AddObjToMappingView(mappingViewMO.m_id, m_hostGroupID, MO_HOST_GROUP, errorDes) != Module::SUCCESS) {
                ERRLOG("Add host group to mapping view failed, host group id:%s, error des:%s",
                    m_hostGroupID.c_str(), errorDes.c_str());
                return Module::FAILED;
            }
        }
        LunGroupMO lunGroupMO;
        GetLunGroupFromMappingView(mappingViewMO.m_id, lunGroupMO, errorDes);
        if (lunGroupMO.m_id.empty()) {
            if (AddObjToMappingView(mappingViewMO.m_id, m_lunGroupID, MO_LUNGROUP, errorDes) != Module::SUCCESS) {
                ERRLOG("Add lun group to mapping view failed, lun group id:%s, error des:%s",
                    m_lunGroupID.c_str(), errorDes.c_str());
                return Module::FAILED;
            }
        }
    }
    DBGLOG("Init v3 device set finish.");
    return Module::SUCCESS;
}

/**
 *  @brief 取消映射集合：从LUN组中移除LUN，不删映射视图（可能其他LUN还在使用）
 *
 *  @return 成功返回 SUCCESS，出错返回 Module::FAILED
 */
int32_t V3ApiOperator::DeleteMappingSet(const std::string& objId, MO_TYPE objType)
{
    INFOLOG("Start to delete mapping set(lun group - lun), obj id:%s", objId.c_str());
    int iRet = RemoveObjFromLunGroupExp(m_lunGroupName, objId, objType);
    if (iRet != Module::SUCCESS) {
        ERRLOG("Remove obj from lun group failed, lun group: %s, obj id: %s, obj type %d",
            m_lunGroupName.c_str(), objId.c_str(), objType);
        return iRet;
    }
    INFOLOG("Delete mapping set success(lun group - lun), obj id:%s", objId.c_str());
    return Module::SUCCESS;
}
}